package cn.swenty.backstage.framework.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import cn.swenty.backstage.framework.common.util.StringUtil;

public class HttpUtil {
	
	private static Logger log=Logger.getLogger(HttpUtil.class);

	public static String httpPostFile(String url, File file) {

		if (!file.exists()) {
			return null;
		}
		PostMethod postMethod = new PostMethod(url);
		try {
			// FilePart：用来上传文件的类
			FilePart fp = new FilePart("filepath",file.getName(), file);
			Part[] parts = { fp };
			// 对于MIME类型的请求，httpclient建议全用MulitPartRequestEntity进行包装
			MultipartRequestEntity mre = new MultipartRequestEntity(parts, postMethod.getParams());
			postMethod.setRequestEntity(mre);
			HttpClient client = new HttpClient();
			client.getHttpConnectionManager().getParams().setConnectionTimeout(50000);// 设置连接时间
			int status = client.executeMethod(postMethod);
			if (status == HttpStatus.SC_OK) {
				return (postMethod.getResponseBodyAsString()).replace("\"", "");
			} else {
				return null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 释放连接
			postMethod.releaseConnection();
		}
		return null;

	}

	private static final String APPLICATION_JSON = "application/json;charset=utf-8";

	private static final String CONTENT_TYPE_TEXT_JSON = "text/json";
	
	
	public static String httpPostForm(String urlStr, Map<String, Object> map) throws Exception {
		
		return httpPostForm(urlStr, map, "utf-8");
		
	}
	
	/**
	 * 
	 * Form 表单提交，post方式
	 * 
	 * @param urlStr
	 * @param map
	 * @return
	 * @throws Exception
	 */
	public static String httpPostForm(String urlStr, Map<String, Object> map,String charset) throws Exception {
		URL url = new URL(urlStr);  
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
        connection.setDoOutput(true);
        connection.setRequestMethod("POST");  
        connection.setDoInput(true);  
        connection.setUseCaches(false);
        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), "ISO-8859-1");  
        out.write(toParams(map)); // 向页面传递数据。post的关键所在！  
        out.flush();  
        out.close();  
        // 一旦发送成功，用以下方法就可以得到服务器的回应：  
        String sCurrentLine;  
        String sTotalString;  
        sCurrentLine = "";  
        sTotalString = "";  
        InputStream l_urlStream;  
        l_urlStream = connection.getInputStream();  
        // 传说中的三层包装阿！  
        BufferedReader l_reader = new BufferedReader(new InputStreamReader(l_urlStream,charset));  
        while ((sCurrentLine = l_reader.readLine()) != null) {
            sTotalString += sCurrentLine + "\r\n";  
  
        }  
       return sTotalString.trim();
	}
	
	/**
	 * 
	 * 将Map转成http参数方式
	 * @param map
	 * @return
	 */
	public static String toParams(Map<String, Object> map){
		Iterator<String> iterator = map.keySet().iterator();
		String signStr = "";
		while (iterator.hasNext()) {
			String key = iterator.next();
			Object value = map.get(key);
			if (value != null) {
				if(value.getClass().isArray()){
					String[]ss = (String[]) value;
					for(String s:ss){
						signStr += (key + "=" + s + "&");
					}
				}else if(!value.equals("")){
					signStr += (key + "=" + value + "&");
				}
				
			}
		}
		return signStr;
	}
	
	

	public static String httpPostWithJSON(String url, String encoderJson) throws Exception {
		DefaultHttpClient httpClient = new DefaultHttpClient();
		if(url.startsWith("https")){
			httpClient = wrapClient();
		}
		HttpPost httpPost = new HttpPost(url);
		httpPost.addHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON);
		StringEntity se = new StringEntity(encoderJson, "utf-8");
		se.setContentType(CONTENT_TYPE_TEXT_JSON);
		se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON));
		httpPost.setEntity(se);
		HttpResponse response = httpClient.execute(httpPost);
		if (response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 203) {// 如果状态码为200,就是正常返回
			// 得到返回的字符串
			return EntityUtils.toString(response.getEntity());
		} else {
			throw new Exception("from " + url + " error:" + response.getStatusLine().getStatusCode());
		}
	}

	public static String receivePost(HttpServletRequest request) throws IOException, UnsupportedEncodingException {

		// 读取请求内容
		BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
		String line = null;
		StringBuilder sb = new StringBuilder();
		while ((line = br.readLine()) != null) {
			sb.append(line);
		}

		// 将资料解码
		String reqBody = sb.toString();
		return URLDecoder.decode(reqBody, HTTP.UTF_8);
	}
	
	/**
	 * @param urlAll
	 *            :请求接口
	 * @param httpArg
	 *            :参数
	 * @return 返回结果
	 */
	public static String request(String httpUrl, String httpArg, String charSet, String apiKey) {
		log.info(httpUrl+" "+httpArg);
		BufferedReader reader = null;
		String result = null;
		StringBuffer sbf = new StringBuffer();
		if (StringUtil.isNotNull(httpArg)) {
			httpUrl = httpUrl + (httpUrl.indexOf('?') >= 0 ? "&" : "?") + httpArg;
		}
		try {
			URL url = new URL(httpUrl);
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			if (StringUtil.isNotNull(apiKey)) {
				connection.setRequestProperty("apikey", apiKey);
			}
			connection.setRequestMethod("GET");
			// 填入apikey到HTTP header
			connection.connect();
			InputStream is = connection.getInputStream();
			reader = new BufferedReader(new InputStreamReader(is, charSet));
			String strRead = null;
			while ((strRead = reader.readLine()) != null) {
				sbf.append(strRead);
				sbf.append("\r\n");
			}
			reader.close();
			result = sbf.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public static String urlResolve(String url,Object ... strs){
		for(int i=0;i<strs.length;i++){
			url = url.replace("${"+(i+1)+"}", strs[i]+"");
		}
		return url;
	}
	
	public static DefaultHttpClient wrapClient() {  
        try {  
            SSLContext ctx = SSLContext.getInstance("TLS");  
            X509TrustManager tm = new X509TrustManager() {

				@Override
				public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
					
				}

				@Override
				public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
					
				}

				@Override
				public X509Certificate[] getAcceptedIssuers() {
					return null;
				}
            };  
            ctx.init(null, new TrustManager[] { tm }, null);  
            SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);  
            SchemeRegistry registry = new SchemeRegistry();  
            registry.register(new Scheme("https", 443, ssf));  
            ThreadSafeClientConnManager mgr = new ThreadSafeClientConnManager(registry);  
            return new DefaultHttpClient(mgr);  
        } catch (Exception ex) {  
            ex.printStackTrace();  
            return null;  
        }  
    }   
	
	public static void main(String[] args) {
		try {
			
			System.out.println(HttpUtil.request("http://localhost:8080/open/token/d858b4c5d3b14b06a2df2f043c8be22e", null, "utf-8", null));

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
